package com.smasher.component.activity

import android.content.ComponentName
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatButton
import androidx.appcompat.widget.AppCompatTextView
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.credentials.CreateCredentialResponse
import androidx.credentials.CreatePasswordRequest
import androidx.credentials.CredentialManager
import androidx.credentials.GetCredentialRequest
import androidx.credentials.GetCredentialResponse
import androidx.credentials.GetPasswordOption
import androidx.credentials.PasswordCredential
import androidx.credentials.exceptions.CreateCredentialCancellationException
import androidx.credentials.exceptions.CreateCredentialCustomException
import androidx.credentials.exceptions.CreateCredentialInterruptedException
import androidx.credentials.exceptions.CreateCredentialProviderConfigurationException
import androidx.credentials.exceptions.CreateCredentialUnknownException
import androidx.credentials.exceptions.GetCredentialException
import androidx.credentials.exceptions.publickeycredential.CreatePublicKeyCredentialDomException
import androidx.lifecycle.lifecycleScope
import com.smasher.component.R
import com.smasher.component.api.ApiKotlin
import com.smasher.net.help.TokenManager
import com.smasher.net.util.RequestBodyUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.json.JSONObject

class LoginAccess : AppCompatActivity() {

    val api = ApiKotlin()

    val credentialManager by lazy {
        CredentialManager.create(baseContext)
    }


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContentView(R.layout.activity_login_access)
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }

        loadToken()

        findViewById<AppCompatButton>(R.id.save).setOnClickListener {
            save("admin", "123456")
        }
        findViewById<AppCompatButton>(R.id.query).setOnClickListener {
            query()
        }
        findViewById<AppCompatButton>(R.id.login).setOnClickListener {
            login()
        }
        findViewById<AppCompatButton>(R.id.jump).setOnClickListener {
            gotoView()
        }
    }

    private fun save(username: String, password: String) {
        // Initialize a CreatePasswordRequest object.
        val createPasswordRequest =
            CreatePasswordRequest(
                id = username,
                password = password,
                preferImmediatelyAvailableCredentials = true

            )
        lifecycleScope.launch {
            try {
                val result =
                    credentialManager.createCredential(
                        // Use an activity based context to avoid undefined
                        // system UI launching behavior.
                        this@LoginAccess,
                        createPasswordRequest
                    )
                handleRegisterPasswordResult(result)
            } catch (e: Exception) {
                handleFailure(e)
            }
        }

    }

    private fun handleFailure(e: Exception) {
        when (e) {
            is CreatePublicKeyCredentialDomException -> {
                // Handle the passkey DOM errors thrown according to the
                // WebAuthn spec.
                //handlePasskeyError(e.domError)
                Log.d(TAG, "handleFailure: CreatePublicKeyCredentialDomException")
            }

            is CreateCredentialCancellationException -> {
                // The user intentionally canceled the operation and chose not
                // to register the credential.
                Log.d(TAG, "handleFailure: CreateCredentialCancellationException")
            }

            is CreateCredentialInterruptedException -> {
                // Retry-able error. Consider retrying the call.
                Log.d(TAG, "handleFailure: CreateCredentialInterruptedException")
            }

            is CreateCredentialProviderConfigurationException -> {
                // Your app is missing the provider configuration dependency.
                // Most likely, you're missing the
                // "credentials-play-services-auth" module.
                Log.d(TAG, "handleFailure: CreateCredentialProviderConfigurationException")
            }

            is CreateCredentialUnknownException -> {
                Log.d(TAG, "handleFailure: CreateCredentialUnknownException")
            }

            is CreateCredentialCustomException -> {
                // You have encountered an error from a 3rd-party SDK. If you
                // make the API call with a request object that's a subclass of
                // CreateCustomCredentialRequest using a 3rd-party SDK, then you
                // should check for any custom exception type constants within
                // that SDK to match with e.type. Otherwise, drop or log the
                // exception.
            }

            else -> Log.w(TAG, "Unexpected exception type ${e::class.java.name}")
        }
    }

    private fun handleRegisterPasswordResult(response: CreateCredentialResponse) {
        Log.d(TAG, "handleRegisterPasswordResult: $response")
    }

    /**
     * 查询凭证
     */
    private fun query() {
        lifecycleScope.launch {
            // Retrieves the user's saved password for your app.
            val getPasswordOption = GetPasswordOption(
                allowedProviders = setOf(ComponentName(packageName, javaClass.name))
            )

            val getCredRequest = GetCredentialRequest(
                listOf(getPasswordOption)
            )

            try {
                val result = credentialManager.getCredential(
                    context = this@LoginAccess, // Use an activity-based context.
                    request = getCredRequest
                )
                handleSignIn(result)
            } catch (e: GetCredentialException) {
                // 处理异常
            }
        }
    }


    fun handleSignIn(result: GetCredentialResponse) {
        // Handle the successfully returned credential.
        val credential = result.credential

        when (credential) {
            is PasswordCredential -> {
                val username = credential.id
                val password = credential.password
                // Use id and password to send to your server to validate
                // and authenticate
                Log.d(TAG, "handleSignIn: $username")
            }

            else -> {
                Log.d(TAG, "handleSignIn: other")
            }
        }
    }

    private fun loadToken() {
        val token = TokenManager.instance.getToken()
        Log.d(TAG, "loadToken: $token")
        updateToken(token.toString())
    }

    private fun updateToken(token: String) {
        Log.d(TAG, "updateToken: $token")
        findViewById<AppCompatTextView>(R.id.token).setText(token)
    }

    fun login() {
        lifecycleScope.launch(Dispatchers.IO) {
            val json = JSONObject().apply {
                put("userName", "admin")
                put("password", "hxzPLM!@#123")
            }
            val body = RequestBodyUtil.createJSONBody(json)
            val result = api.submitLogin(body)
            withContext(Dispatchers.Main) {
                Log.d(TAG, "login: $result")
                val token = result.data
                updateToken(token)
                TokenManager.instance.saveToken(token)
                if (result.isSuccess) {
                    gotoView()
                }
            }
        }

    }

    fun gotoView() {
        launcher.launch(Intent().apply {
            setClass(this@LoginAccess, DialogActivity::class.java)
        })
    }

    private val launcher =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult())
        { result ->
            if (result.resultCode == RESULT_OK) {
                finish()
            }
        }

    companion object {
        const val TAG = "LoginAccess"
    }
}